#include "bmploader.h"

#include "tetris.h"

#include "fileinfo.h"

#pragma pack(push, 1)
struct pixel
{
  union {
    unsigned color;
    struct {
      unsigned char blue;
      unsigned char green;
      unsigned char red;
      unsigned char alpha;
    };
  };
};
#pragma pack(pop)

static void set_pixel(struct pixel* p, unsigned char* data)
{
  p->red = data[2];
  p->green = data[1];
  p->blue = data[0];
}
static int get_pixel_24(struct bitmap* b, void* data)
{
  unsigned char* src = (unsigned char*)data;
  struct pixel* dst = (struct pixel*)b->data;
  int i, j;
  int p = (b->width * 3 + 3) & 0xFFFFFFFC;
  int len = sizeof(struct pixel);

  dst += b->width * (b->height - 1);
  for (i = b->height; i > 0; i--, src += p, dst -= b->width) {
    for (j = 0; j < b->width; j++) {
      set_pixel(&dst[j], src + j * 3);
    }
  }
  return (1);
}
static int get_pixel_32(struct bitmap* b, void* data)
{
  unsigned char* src = (unsigned char*)data;
  struct pixel* dst = (struct pixel*)b->data;
  int i, j;
  int p = b->width * 4;
  int len = sizeof(struct pixel);

  dst += b->width * (b->height - 1);
  for (i = b->height; i > 0; i--, src += p, dst -= b->width) {
    for (j = 0; j < b->width; j++) {
      set_pixel(&dst[j], src + j * 4);
    }
  }
  return (1);
}
static int get_pixel(struct bitmap* bmp, BITMAPFILEHEADER* bf, BITMAPINFOHEADER* bi)
{
  unsigned char* bits = (unsigned char*)bf + bf->bfOffBits;
  switch (bi->biBitCount)
  {
  case 24:
    return (get_pixel_24(bmp, bits));
  case 32:
    return (get_pixel_32(bmp, bits));
  default:
    return (0);
  }
  return (1);
}

struct bitmap* get_bmp_data(char* bmp_file)
{
  BITMAPFILEHEADER* bf;
  BITMAPINFOHEADER* bi;
  struct bitmap* bmp = 0;
  int size;

  struct file_info* file = open_file(bmp_file);
  if (file == 0) {
    return (0);
  }

  bf = (BITMAPFILEHEADER*)(file->data);
  if (bf->bfType != 'MB') {
    goto Exit0;
  }
  bi = (BITMAPINFOHEADER*)((unsigned char*)file->data + sizeof(BITMAPFILEHEADER));
  bmp = (struct bitmap*)malloc(sizeof(*bmp));
  bmp->width = bi->biWidth, bmp->height = bi->biHeight;
  size = bmp->width*bmp->height*sizeof(struct pixel);
  bmp->data = (unsigned char*)malloc(size);
  memset(bmp->data, 0, size);
  get_pixel(bmp, bf, bi);

Exit0:
  close_file(file);
  return (bmp);
}

void destroy_bmp_data(struct bitmap* bmp)
{
  if (bmp != 0) {
    free(bmp->data);
    free(bmp);
  }
}
